package uk.ac.ncl.carrent;


import java.util.*;

/**
 * LicenceNumber - The licence number has three components. 
 * The first component is the concatenation of the initial of the first name of the driver 
 * with the initial of the last name of the driver. 
 * The second component is the year of issue of the licence. 
 * The third component is an arbitrary serial number. The number is up to 100.
 * 
 * @author Shiwei He
 * 
 */

public final class LicenceNumber {

	private final String initials;
	private final int year;
	private final int serialNumber;
	private final String number;
	private static final Map<String, LicenceNumber> numbers = new HashMap<String, LicenceNumber>();
	
	
	private LicenceNumber(String initials, int year, int serialNumber){
		this.initials = initials;
		this.year = year;
		this.serialNumber = setSerialNumber();
		number = initials + "-" + year + "-" + serialNumber;
	}
	
	/*
	 * get a new instance of the LicenceNumber, given person, issueDate and serialNumber
	 * @param person the driver
	 * @param issueDate the issue date of the licence
	 * @param serialNumber the serial number of the licence number
	 * @return licence number which is unique
	 * @throws IllegalArgumentException if the issue date is before the date of birth or after the current date.
	 */
	public final static LicenceNumber getInstance(Person person, Calendar issueDate, int serialNumber){
		String lnumber = person.getInitials() + issueDate.get(Calendar.YEAR) + serialNumber;
		LicenceNumber licence = numbers.get(lnumber);
		if(licence == null){
			if(issueDate.get(Calendar.YEAR) < person.getDob().get(Calendar.YEAR))
				throw new IllegalArgumentException("Invalid issue date.");
			if(issueDate.get(Calendar.YEAR) > Calendar.getInstance().get(Calendar.YEAR))
				throw new IllegalArgumentException("Invalid issue date.");
			final String initials = person.getInitials();
			final int year = person.getDob().get(Calendar.YEAR);
			licence = new LicenceNumber(initials, year, serialNumber);
			numbers.put(licence.getNumber(), licence);
		}
			return licence;
	}
	
	/**
	 * get a new random serial number within the range [0,100)
	 * @return int a random serial number within [0,100)
	 */
	public int setSerialNumber(){
		Random randomGenerater = new Random();
		return randomGenerater.nextInt(100);
	}
	
	/**
	 * get the initials of the person
	 * @return String the initials of the person's name
	 */
	public String getInitials(){
		return initials;
	}
	
	/**
	 * get the issue year of the licence
	 * @return int the issue year of the licence
	 */
	public int getYear(){
		return year;
	}
	
	/**
	 * get the serial number of the licence number
	 * @return int the serial number of the licence number
	 */
	public int getSerialNumber(){
		return serialNumber;
	}
	
	private String getNumber(){
		return number;
	}
	
	/**
	 * given a string of the licence number, generate a licence number
	 * @param String the licence number in format initials-year-serialnumber
	 * @return LicenceNumber the licence number
	 */
	public static LicenceNumber valueOf(String number){
		LicenceNumber licence = numbers.get(number);
		if(licence == null){
			final String[] parts = number.split("-");
			return new LicenceNumber(parts[0], Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
		}
		return licence;
	}
	
	
	/**
	 * get the String which represents the licence number with format:
	 * initials(first character of the first name + first character of the last name)-issue year(yyyy)-serial number(nnn)
	 * 
	 * @see java.lang.Object#toString()
	 */
	public String toString(){
		return initials.toUpperCase() + "-" + year + "-" + serialNumber;
	}
	

}
